home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / PostScriptFiles / FillProcs.ps < prev    next >
Encoding:
Text File  |  2000-09-28  |  39.2 KB  |  1,307 lines  |  [TEXT/MPS ]

  1. %
  2. %    File:        FillProcs.ps
  3. %
  4. %    Contains:    This file contains Procedures the procedures used for Skia clips and fills.
  5. %
  6. %    Version:    Technology:    Quickdraw GX 1.1.x.
  7. %
  8. %    Copyright:    © 1991-7 by Apple Computer, Inc., all rights reserved.
  9. %
  10. %
  11.  
  12.  
  13. %        File contains the following Procedures:
  14. %            ShapeBuildChar      (Internally referenced only)
  15. %            MakeShapeFont            (Internally referenced only)
  16. %            PatternFill                (Internally referenced only)
  17. %            MakePatternDict
  18. %            QD2Fill
  19. %            QD2Clip
  20. %            QD2Show
  21. %            DashStroke
  22. %            MakeDashDict
  23. %
  24. %            Also contains dictionaries (PatternFillDict, FillDict, ClipDict)
  25. %                which contain the procedures for the various types of Skia fills.
  26.  
  27.  
  28.  
  29.  
  30.  
  31. %<FF>
  32. %
  33. %        First we need procedures for patterns:
  34. %
  35. %
  36. languagelevel 2 lt {
  37.     %    The shape buildchar procedure, draws the shape for a font.  Only done in Level-1
  38.     %
  39.     %        Set up the font cache.  
  40.     %            Use the FontBBox for the cache and ux, uy for the advance
  41.     %        Execute the geometry
  42.     %        Execute the paint operator
  43.     %
  44.     %    fontDict glyphCode ShapeBuildChar -
  45.     %
  46.     %        fontDict:        The pattern font's dictionary.
  47.     %        glyphCode:    The id of the character to draw, we don't really care what character, however.
  48.     %
  49.     /ShapeBuildChar {
  50.     
  51.         pop                                                                            % We don't care what the glyph code is.
  52.         begin                                                                        % Put the font dictionary at top of stack.
  53.     
  54.             0 setlinewidth                            % If it is framed, it is always hairline.  (Skia definition)
  55.                     
  56.             Shape begin                                                            % Put shape dictionary on stack.
  57.             
  58.                 %    Set up the font cache.
  59.                 AdvanceVector dup 0 get exch 1 get        % Advance width for font cache.
  60.                         
  61.                 shapeType /i ne {                                                %    If it is not a deep bitmap pattern
  62.                 
  63.                     x1 y1 Grid x2 y2 Grid setcachedevice    %        set up the cache bounding box.
  64.                     geomProc                                                            %        Execute the geometry
  65.                     FillDict fillKey get exec                            %        Paint it. (superfluous for 1-bit bitmaps but check would be extra work)
  66.                     
  67.                 } {                                                                            % Else
  68.                                 
  69.                     setcharwidth                                                    %        Just set up advance widths.
  70.                     geomProc                                                            %        Execute the shape (paints itself)
  71.                     
  72.                 } ifelse
  73.                 
  74.             end
  75.                         
  76.         end
  77.         
  78.     } Bdef
  79.  
  80. } {
  81.  
  82.     %% Paint procedure for level-2 pattern dictionaries.
  83.     
  84.     /PatternPaintProc {
  85.     
  86.         begin                                                % Make the pattern dictionary the current top dictionary.
  87.     
  88.             IpatTransform concat            % Transform CTM by inverse pattern matrix.
  89.             
  90.             patShape begin                        % Put shape dictionary on the dict stack.
  91.             
  92.                 CurrColorSet                        % Save the old color set on the stack.
  93.                 
  94.                 colorSet SetColorSet        % Get the shape's color set, make it current.
  95.                 ColorSpace null ne {        % If the shape has a level-2 color space (should never have both colorSet and space)
  96.                 
  97.                     ColorSpace GXSetCSpace        % set it
  98.                     
  99.                 } if
  100.                 
  101.                 shapeType /b eq {                % For one bit bitmap patterns, deal with foreground/background color
  102.                 
  103.                     CurrOrMode 0 eq {            %        If not or mode, draw rectangle in background color
  104.                     
  105.                         0 colorSet SetIndexedColor        % Set color to background color.
  106.                         newpath
  107.                         x1 y1 moveto x2 y1 lineto
  108.                         x2 y2 lineto x1 y2 lineto
  109.                         closepath
  110.                         fill
  111.                     
  112.                     } if
  113.                     
  114.                     ImageMaskColor colorSet SetIndexedColor            % set the color to the ImageMask color
  115.                 
  116.                 } if
  117.                 
  118.                 newpath                                    % Make sure there is no current path.
  119.                 geomProc                                % Execute the geometry procedure.
  120.                 
  121.                 FillDict fillKey get exec        % Paint it with the proper fill procedure for the fill type.
  122.             
  123.                 SetColorSet                            % Restore the old colorset.
  124.                 
  125.             end
  126.                 
  127.         end
  128.     
  129.     } Bdef
  130.     
  131. } ifelse                        % level 1 or level 2
  132.  
  133.  
  134. %<FF>
  135. %
  136. %        Procedure:  MakeShapeFont
  137. %            Makes a type-3 font describing for drawing a geometry. used for level-1 patterns.
  138. %
  139. % shape ux uy MakeShapeFont dict
  140. %
  141. %        shape:                A valid shape dictionary
  142. %        ux, uy:                The x and y components of the U vector in the pattern.
  143. %        
  144. languagelevel 2 lt {                % Only needed for level 1.
  145.  
  146.     /MakeShapeFont {
  147.     
  148.         8 dict dup begin                    % Make a dictionary, put it on the dict stack, save a copy.
  149.         
  150.             4 1 roll                                % Put duplicate dictionary at bottom of the stack.
  151.             
  152.             [3 1 roll]
  153.             /AdvanceVector Xdef            % Save ux, uy in an array so we can write into it.
  154.             
  155.             /Shape Xdef
  156.                     
  157.             %
  158.             %    Now Define required entries in the font dictionary.
  159.             %
  160.             /FontType 3 def
  161.             /FontMatrix [1 0 0 1 0 0] def                            % The pattern should be in correct space.
  162.             
  163.             /FontBBox [                                                                %    The bounding box
  164.                 Shape ShapeBBox
  165.             ] def
  166.             
  167.             /Encoding StandardEncoding def                        % Just becuase it's a required entry, won't use it.
  168.             
  169.             /BuildChar /ShapeBuildChar load def
  170.                 
  171.         end
  172.     
  173.     } Bdef
  174.  
  175. } if                    % level-1 only
  176.  
  177.  
  178.  
  179.  
  180. %<FF>
  181. %
  182. %        Function checks a matrix to see if it a scale only (no rotation - except 90, 180, 270 -
  183. %            no skewing, translation allowed)
  184. %
  185. %        matrix IsMatrixJustScaling matrix justscale
  186. %
  187. %            matrix:            input matrix (left on stack after execution behind boolean)
  188. %            justScale:    Boolean, true if matrix is just scaling, false otherwise
  189. %
  190. /IsMatrixJustScaling {
  191.  
  192.     % Check diagonals of             *********
  193.     %                                                     * a b 0 *
  194.     %                                                     * c d 0 *
  195.     %                                                     * e f 1 *
  196.     %                                                     *********
  197.     
  198.     dup 0 get                                % Stack is: matrix a
  199.     1 index 3 get                        % Stack is: matrix a d
  200.     0.0 eq exch 0.0 eq and    % Stack is: matrix FirstDiagonalEqual
  201.     
  202.     1 index 1 get                        % Stack is: matrix FirstDiagonalEqual b
  203.     2 index 2 get                        % Stack is: matrix FirstDiagonalEqual b c
  204.     0.0 eq exch 0.0 eq and    % Stack is: matrix FirstDiagonalEqual SecondDiagonalEqual
  205.     or                                            % Stack is: matrix matrixJustScaled
  206.     
  207. } Bdef
  208.  
  209. %
  210. % Watch out for rentrancy problems here if patterns 
  211. %            can ever go recursive (ie pattern could be shape with pattern)
  212. %        these globals could get mucked up.
  213. /PortMapping matrix def
  214. /PortPatternMapping matrix def                                % Port Mapping to be used for the pattern.
  215. /SaveCTMForPattern matrix def                                    % Save the CTM
  216.  
  217.  
  218. %
  219. %        Function grids a matrix if it is only a scale matrix (90 degree rotations allowed)
  220. %            Used for PortPatternMapping to ensure integer scaling of patterns
  221. %
  222. /GridMatrix {
  223.     
  224.     IsMatrixJustScaling {        % If the matrix is just a scaling matrix.
  225.     
  226.         % If the matrix is not rotated or skewed then round off the scaling.
  227.         
  228.         0 1 3 {            % Just the first 4 elements of the matrix.
  229.         
  230.             dup                                     %    Stack is matrix index index
  231.             2 index exch                    % Stack is matrix index matrix index
  232.             get dup abs 1.0 gt {    % Only round for scales > 1
  233.                 round                                %     Stack is matrix index round(matrix[index])
  234.             } if
  235.             2 index                                % Stack is matrix index round(matrix[index]) matrix
  236.             3 1 roll put                    % Stack is matrix
  237.                         
  238.         } for
  239.         
  240.     } if
  241.     
  242.     pop                % Pop off extra copy of matrix.
  243.  
  244. } Bdef
  245.  
  246.  
  247.  
  248. %<FF>
  249. %
  250. %        Routine ensures that a matrix that looks like it should really be
  251. %            non-scaling is non-scaling.  We do this because sometimes round
  252. %            off error on high resolution printers makes matrices that should
  253. %            cause device resolution drawings are somtimes off by a small amount
  254. %            This throws postscript bitmap rendering into the slow case, and the
  255. %            reason we are doing the stuff as device resolution bitmaps is for speed.
  256. %
  257. /EnsureDeviceResolution {
  258.  
  259.     ScratchMatrix currentmatrix    IsMatrixJustScaling     {
  260.  
  261.         % If the scale components are near 1, make them 1.
  262.         0 1 3 {        % Loop on first 4 elements of matrix. (everything but translation values)
  263.             
  264.             dup 2 index exch                                            % Get the element of the matrix
  265.             get dup abs 1.0 sub abs    .005 le {            % Is the component near 1.0 (within 0.5%)?
  266.             
  267.                 % Force value to be 1.0, signed same as original.
  268.  
  269.                 0.0 lt {
  270.                     -1.0                
  271.                 } {
  272.                     1.0
  273.                 } ifelse
  274.                 
  275.             } if
  276.  
  277.             2 index 3 1 roll put             % Put the new value in the matrix
  278.         
  279.         } for
  280.     
  281.     } if
  282.     
  283.     % Stack contains either unmodified matrix or adjusted one, either way:
  284.     setmatrix            
  285.  
  286. } Bdef
  287.  
  288. %
  289. %        Procedure: SetupPatternCTM
  290. %        Procedure sets up the CTM for the rendering of the pattern based upon the 
  291. %        PortMap and PortAllign attributes. Old CTM is saved in SaveCTMForPattern
  292. %        Only Rob Johnson can explain the whole reason why the CTMs are translated this way.
  293. %
  294. %        The pattern must be on the dictionary stack.
  295. %            SetupPatternCTM -
  296. %
  297. /SetupPatternCTM {
  298.  
  299.     SaveCTMForPattern currentmatrix pop
  300.     
  301.     PortMap    {                    % If port Map is true (must be a bitmap pattern)
  302.     
  303.         PortMapping PortPatternMapping
  304.         copy dup GridMatrix                                % Grid the matrix for bitmap patterns.
  305.         setmatrix                                                    % Make the current space the port space.
  306.         PortAllign not {                                    % If not port alligned then translate appropriately.
  307.             
  308.             % Get location of shape 0,0 in current (port) space and allign to it.
  309.             
  310.             0 0 SaveCTMForPattern transform    itransform 
  311.             translate
  312.             
  313.         } if
  314.     
  315.     } {                                % Else PortMap is false
  316.     
  317.         PortAllign {        %        If PortAllign is true, then translate the CTM
  318.         
  319.             % Get location of port 0,0 is in user space and allign to it.
  320.             
  321.             0 0 PortMapping transform itransform
  322.             translate
  323.  
  324.         } if
  325.     
  326.     } ifelse
  327.     
  328. } Bdef
  329.  
  330.  
  331. %    Procedure MakePatternDict:
  332. %        Procedure makes a valid pattern dictionary for the PatternFill operator.
  333. %        It computes the pattern matrices based upon the lattice parameters.
  334. %
  335. % shape ux uy vx vy px py PortMap PortAllign MakePatternDict dict
  336. %
  337. %        shape:                A valid shape dictionary
  338. %        ux, uy:                The u vector from the pattern record.
  339. %        vx, vy:                The v vector from the pattern record.
  340. %        px, py:                The phase of the pattern.  (Skia currently doesn't do this, pass 0, 0)
  341. %        PortMap                Boolean, gxPortMapPattern on or off.
  342. %        PortAllign        Boolean, gxPortAlignPattern on or off.
  343. %        dict:                    Created, a valid pattern dictionary.
  344. %
  345. languagelevel 2 lt {
  346.     /MakePatternDict {
  347.     
  348.         21 dict dup begin                                %    Make the dictionary and leave it on the stack
  349.         
  350.             10 1 roll                                            %    Roll the duplicate dictionary back before the parameters.
  351.             
  352.             /PortAllign Xdef
  353.             /PortMap Xdef
  354.             /py Xdef /px Xdef
  355.             /vy Xdef /vx Xdef
  356.             /uy Xdef /ux Xdef
  357.             
  358.             /patTransform [                                % Make the matrix from parameters.
  359.             
  360.                 ux uy
  361.                 vx vy
  362.                 px py
  363.             
  364.             ] def
  365.             
  366.             %    Stack is shape:
  367.             % If the shape is a 1-bit bitmap (/b) and the lattice is different from the bitmap's dimensions
  368.             %        Change the shape type to image (/i) to prevent patternfill from doing a fill of the background
  369.             %        color - /i makes Draw1bitBitmapString do it instead on a per stamp basis.
  370.             
  371.             dup /shapeType get /b eq {
  372.             
  373.                 dup ShapeBBox                % Stack is: shape x1 y1 x2 y2
  374.                 BoxWidths                        % Stack is: shape width height
  375.                 
  376.                 vy ne vx 0 ne or                % Stack is: shape width (height!=vy || vx!=0)
  377.                 exch ux ne uy 0 ne or        % Stack is: shape (width!=ux || uy!=0) (height!=vy || vx!=0)
  378.                 or {                                        % If either is true, change shapeType.
  379.                 
  380.                     dup /shapeType /i put
  381.                 
  382.                 } if
  383.                 
  384.             } if
  385.             
  386.             % Stack is left: shape, ready to make the font, Get advance width for the character.
  387.                         
  388.             ux uy MakeShapeFont                        % Make a font out of the pattern shape using the u vector as advance.
  389.             
  390.             /patternFont exch definefont    % Give the font the name "patternFont"  It may have to be unique,
  391.                                                                         %        If we find this out later, I'll fix it.
  392.                                                                         
  393.             /patternFontDict Xdef                    % Save the font dictionary in the pattern dictionary.
  394.                     
  395.             /IpatTransform                                % Get the inverse of the matrix
  396.                 patTransform matrix
  397.                 invertmatrix
  398.             def
  399.     
  400.         end
  401.         
  402.     } Bdef
  403.  
  404. } {    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% level-2 version of MakePatternDict.
  405.  
  406.     /MakePatternDict {
  407.     
  408.         10 dict dup begin                                %    Make the dictionary and leave it on the stack
  409.         
  410.             10 1 roll                                            %    Roll the duplicate dictionary back before the parameters.
  411.             
  412.             /PatternType 1 def                        % 1 is what the book says to use.
  413.             /PortAllign Xdef                            % Get PortAllign boolean.
  414.             /PortMap Xdef                                    % Get PortMap boolean.
  415.             [ 7 1 roll ]                                    % Make the matrix
  416.             /patTransform Xdef                        %    Save it in the dictionary
  417.                         
  418.             /XStep 1 def                                    % Run through the pattern transform yields Skia's U and V.
  419.             /YStep 1 def
  420.     
  421.             /TilingType CurrGridFit {2} {1} ifelse def                    % Base it on grid fit from style.
  422.     
  423.             /PaintProc /PatternPaintProc load def                                % Get a copy of the pattern procedure.
  424.  
  425.             /IpatTransform                                % Get the inverse of the matrix
  426.                 patTransform [0 0 0 0 0 0]
  427.                 invertmatrix
  428.             def
  429.  
  430.             /patShape Xdef                                % Save the shape dictionary.
  431.             
  432.             %
  433.             % Get the tightest bounding box, this is very performance criticle.
  434.             %            small errors can make big speed hits.
  435.             %            e.g:  if bbox is just 2x as big, speed hit is 3-4x.
  436.             %
  437.             /BBox [
  438.             
  439.                 gsave
  440.  
  441.                 ScratchMatrix currentmatrix                            % Save the current matrix on the stack.
  442.                 IpatTransform concat                                        % Concatonate the inverse pattern matrix.
  443.  
  444.                 patShape /shapeType get /g eq {                                % If it is a geometric shape then:
  445.                 
  446.                     patShape /geomProc get exec                                    %        execute the geometry procedure.
  447.                     setmatrix                                                                        %        put the matrix back.
  448.                     /flattenpath 0 AvoidLimit pathbbox                    %        Get the tight bounding box.
  449.                     
  450.                 } {                                                                                        %    else
  451.                 
  452.                     patShape ShapeBBox                                                    %        Get bounding box from shape dictionary.
  453.                     4 2 roll 4 copy 4 2 roll BoxWidths RP                %        Make it into a path.
  454.                     pop pop
  455.                     setmatrix                                                                        %        Restore the CTM
  456.                     pathbbox                                                                        %        Get bounding box of transformed rectangle.
  457.                     
  458.                 } ifelse
  459.                 
  460.                 grestore
  461.                 
  462.             ] def
  463.             
  464.             %
  465.             %        Assign the paint type based on the shape type
  466.             %            
  467.             /PaintType 
  468.             
  469.                 %% bitmap patterns are colored patterns.
  470.                 
  471.                 patShape /shapeType get dup /i eq exch /b eq or {                % If it is bitmap then
  472.                         1                                                                    %     painttype is colored pattern.
  473.                 } {                                                                        % else
  474.                         2                                                                    %     painttype is uncolored pattern.
  475.                 }ifelse                
  476.                 
  477.             def
  478.     
  479.         end
  480.  
  481.         dup /patTransform get                    % Get the transform to pass to makepattern
  482.         makepattern                                        % Just make the pattern
  483.                     
  484.     } Bdef
  485.     
  486. } ifelse            % level-1 or level-2
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493. %<FF>
  494. %
  495. %    Fill the current path with the pattern described by the dictionary.
  496. %
  497. %        Only needed for level-1.
  498. %        boolean patternDict PatternFill -
  499. %
  500. %            boolean:            true means winding-number, false means even-odd
  501. %            pattermDict:    a valid pattern dictionary.
  502.  
  503. languagelevel 2 lt {
  504.  
  505. %
  506.     /patternString 100 string def                % Allocate a hundred byte string for pattern stamping.
  507.  
  508.     /PatternFill {
  509.     
  510.         CurrPat begin                            % Put the pattern dict at top of dict stack
  511.         
  512.             gsave                                        % Save the current clip and CTM - we'll muck with it to fill with the pattern.
  513.             
  514.             SetupPatternCTM                    % Fix up user space for PortAllign and PortMap
  515.                         
  516.             % The boolean is on the stack to Determine even-odd fill or winding-number fill.
  517.             
  518.             % If it is a bitmap pattern, handle the colorset, don't have to worry about space, this is a level-1 proc only:
  519.             
  520.             patternFontDict /Shape get /shapeType get /b eq {
  521.             
  522.                 CurrOrMode 0 eq {                        % if not or-mode, fill the shape with background color
  523.                 
  524.                     0 patternFontDict /Shape get /colorSet get SetIndexedColor        % set color to background.
  525.                     
  526.                     dup                                                                                                                        % duplicate the boolean for even-odd
  527.                     gsave {fill} {eofill} ifelse grestore                                                    % fill the shape
  528.                 
  529.                 } if
  530.             
  531.                 ImageMaskColor patternFontDict /Shape get /colorSet get SetIndexedColor            % Set color to Image Mask color.
  532.             
  533.             } {            % If the shape, otherwise has a colorSet (only indexed bitmaps should) install it.
  534.             
  535.                 patternFontDict /Shape get /shapeType get /i eq {
  536.                 
  537.                     patternFontDict /Shape get dup /colorSet get dup                 % Stack is shapeDict shapeDict colorSet colorSet
  538.                     
  539.                     null ne {            % If the colorset is not null
  540.                     
  541.                         SetColorSet                                                                                                        %        Set the colorSet if it has one.
  542.                     
  543.                         /BitsPerPixel get 2 exch exp 1 sub /MaxSampleInt exch store        %        Get bits/pixel from shape, Set the maxSample
  544.                         
  545.                         InstallColorSetTransfers                                                                            %     They will be de-installed by the grestore at the end of PatternFill        
  546.                         
  547.                     } {
  548.                     
  549.                         pop                        % Pop off the duplicate shape dictionary
  550.                         pop                        % Pop off the null from duplicating the colorSet entry in the shape dictionary
  551.                         
  552.                     } ifelse
  553.                     
  554.                 } if
  555.                             
  556.             } ifelse
  557.             
  558.             {/clip 0 AvoidLimit}
  559.             {/eoclip 0 AvoidLimit}
  560.             ifelse        % Make the current path the clip based on boolean
  561.         
  562.             /flattenpath 0 AvoidLimit        % Make sure we get an accurate bounding box
  563.             /pathbbox    load stopped            % Get the current path bounding box on the stack
  564.             {0 0 0 0} if                                % if pathbbox failed just put a 0 bounding box on the stack.
  565.                                                                     %   It fails on things like "0 0 moveto 0 0 rlineto strokepath"
  566.             newpath                                            % Don't leave flattened path around, it takes up valuable path room
  567.         
  568.             % Now stack is x1 y1 x2 y2            (The fill path's bounding box)
  569.             
  570.             patternFontDict dup setfont                 % Make patternFont current font
  571.             /FontBBox get                                                % get the bbox
  572.             {} forall BoxWidths                                    % How wide is the pattern?
  573.             
  574.             % Stack is now x1 y1 x2 y2 Wx Wy
  575.             6 2 roll                                                    % Stack is now Wx Wy x1 y1 x2 y2
  576.             
  577.             % Expand the current path's box by the width of the pattern:
  578.             
  579.                                                                                 % Stack:
  580.             4 index add                                                %  Wx Wy x1 y1 x2 (y2 + Wy)
  581.             exch                                                            %  Wx Wy x1 y1 (y2 + Wy) x2
  582.             5 index add                                                %  Wx Wy x1 y1 (y2 + Wy) (x2 + Wx)
  583.             4 2 roll                                                    %  Wx Wy (y2 + Wy) (x2 + Wx) x1 y1
  584.             4 index sub                                                %  Wx Wy (y2 + Wy) (x2 + Wx) x1 (y1 - Wy)
  585.             exch                                                            %  Wx Wy (y2 + Wy) (x2 + Wx) (y1 - Wy) x1
  586.             5 index sub                                                %  Wx Wy (y2 + Wy) (x2 + Wx) (y1 - Wy) (x1 - Wx)
  587.             
  588.             exch 4 2 roll exch                                %     Wx Wy (x1 - Wx) (y1 - Wy) (x2 + Wx) (y2 + Wy)
  589.             
  590.             /y2 Xdef
  591.             /x2 Xdef
  592.             /y1 Xdef
  593.             /x1 Xdef
  594.             
  595.             % Find the bounding box in pattern space.
  596.             %        x1' = Min of X coordinates of all 4 corners.
  597.             %        x2' = Max of X coordinates of all 4 corners.
  598.             %        y1' = Min of Y coordinates of all 4 corners.
  599.             %        y2' = Max of Y coordinates of all 4 corners.
  600.             
  601.             x1 y1 IpatTransform transform pop                    % Get x' component of vector (x1,y1)
  602.             x1 y2 IpatTransform transform pop                    % Get x' component of vector (x1,y2)
  603.             Min                                                                                % Which one is smaller?
  604.             
  605.             x2 y1 IpatTransform transform pop                    % Get x' component of vector (x2,y1)
  606.             x2 y2 IpatTransform transform pop                    % Get x' component of vector (x2,y2)
  607.             Min                                                                                % Which one is smaller?
  608.             
  609.             Min floor /x1p Xdef                                                            % Get smallest of all 4.
  610.     
  611.             x1 y1 IpatTransform transform pop                    % Get x' component of vector (x1,y1)
  612.             x1 y2 IpatTransform transform pop                    % Get x' component of vector (x1,y2)
  613.             Max                                                                                % Which one is bigger?
  614.             
  615.             x2 y1 IpatTransform transform pop                    % Get x' component of vector (x2,y1)
  616.             x2 y2 IpatTransform transform pop                    % Get x' component of vector (x2,y2)
  617.             Max                                                                                % Which one is bigger?
  618.             
  619.             Max ceiling /x2p Xdef                                                            % Get biggest of all 4.
  620.             
  621.             x1 y1 IpatTransform transform exch pop        % Get y' component of vector (x1,y1)
  622.             x2 y1 IpatTransform transform exch pop        % Get y' component of vector (x2,y1)
  623.             Min                                                                                % Which one is smaller?
  624.             
  625.             x1 y2 IpatTransform transform exch pop        % Get y' component of vector (x1,y2)
  626.             x2 y2 IpatTransform transform exch pop        % Get y' component of vector (x2,y2)
  627.             Min                                                                                % Which one is smaller?
  628.     
  629.             Min floor /y1p Xdef                                                            % Get smallest of all 4.
  630.             
  631.             x1 y1 IpatTransform transform exch pop        % Get y' component of vector (x1,y1)
  632.             x2 y1 IpatTransform transform exch pop        % Get y' component of vector (x2,y1)
  633.             Max                                                                                % Which one is Bigger?
  634.             
  635.             x1 y2 IpatTransform transform exch pop        % Get y' component of vector (x1,y2)
  636.             x2 y2 IpatTransform transform exch pop        % Get y' component of vector (x2,y2)
  637.             Max                                                                                % Which one is bigger?
  638.             
  639.             Max ceiling /y2p Xdef                                                            % Get biggest of all 4.
  640.     
  641.             /x1p x1p floor def
  642.             /y1p y1p floor def
  643.             /x2p x2p ceiling def
  644.             /y2p y2p ceiling def
  645.             
  646.             pop pop                                                    % Get rid of the widths.
  647.             
  648.             
  649.                     
  650.             % Now stamp the pattern across the lattice defined by the bounding box in pattern space.
  651.     
  652.             % Calculate the width of the pattern lattice
  653.             /lattWidth x2p x1p sub 1 add cvi def
  654.     
  655.             % Walk the lattice vertically
  656.             y1p 1 y2p {
  657.     
  658.                 x1p exch patTransform transform moveto        % Move to the next position in the lattice.
  659.                 
  660.                 0 100 lattWidth {                            % As many times as it takes for width given string size.
  661.     
  662.                     lattWidth exch sub                                            %     How much of this scan is left to stamp?
  663.                     dup 100 gt {                                                        %     If it is bigger than the string then
  664.                         pop 100                                                                %            current length is string length
  665.                     } if                                                                        %        else we can do as many as we asked for
  666.                     patternString 0 3 -1 roll getinterval        %     Get a substring no bigger than we need.
  667.                     show                                                                        %     show it.
  668.     
  669.                 } for                
  670.     
  671.             } for
  672.                     
  673.             grestore
  674.             newpath
  675.             
  676.         end
  677.         
  678.     } Bdef
  679.     
  680. } if                    % defined for level 1 only.
  681.  
  682.  
  683. %<FF>
  684. %    Procedure PathLength:
  685. %        Procedure finds the length of the current path, leaves the path flattened.
  686. %    
  687. %        - PathLength L
  688. %
  689. %                L is length of path, left on stack.
  690. %
  691. /PathLength {
  692.  
  693.     /@1 0 def                                % initialize the length.
  694.     
  695.     { /@3 Xstore /@2 Xstore }            % moveto procedure,  @2 is X, @3 is Y
  696.     
  697.     { 2 copy                                    % lineto procedure:
  698.             @3 sub dup mul                %     Get (y2-y1)^2
  699.             exch @2 sub dup mul        %     Get (x2-x1)^2
  700.             add sqrt                            %     Get length of vector
  701.             @1 add /@1 Xdef                %      Accumulate total length.
  702.             /@3 Xstore /@2 Xstore    %     Get new x1, y1
  703.     }
  704.     {}                                                % curveto procedure, assumes path is flattened.
  705.     {}                                                % closepath procedure.
  706.     
  707.     /flattenpath 0 AvoidLimit    % Flatten the path.
  708.     
  709.     pathforall
  710.     
  711.     @1                                                % Leave length on stack.
  712.     
  713. } Bdef
  714.  
  715.  
  716. %<FF>
  717. %    Procedure MakeDashDict:
  718. %        Procedure makes a valid dash dictionary for the DashStroke operator.
  719. %
  720. % shape autoAdvance level breakDash advance phase scale MakeDashDict dict
  721. %        
  722. %        shape:            A valid shape dictionary
  723. %        autoAdvance boolean, autoAdvance on or off.
  724. %        levelDash:    boolean, level-dash on or off.
  725. %        breakDash:    boolean, break-dash on or off.
  726. %        advance:        The advance of the dash.
  727. %        phase:            The phase of the dash.
  728. %        scale:            The scale of the dash.
  729. %
  730. %        dict:                    Created, a valid pattern dictionary.
  731. %
  732. /MakeDashDict {
  733.  
  734.     16 dict begin                                %    Make the dictionary and leave it on the stack
  735.     
  736.         /dashScale Xdef                                %   Virtual scaling for dash shape.
  737.         /phase Xdef                                        %        Phase of the dash
  738.         /advance Xdef                                    %        Get the advance of the dash
  739.         /breakDash Xdef                                %        Get the break-dash bit.
  740.         /levelDash Xdef                                %        Get the level-dash bit.
  741.         /autoAdvance Xdef                            %        Get the autoAdvance bit.
  742.         
  743.         /Shape Xdef                                        %        Get the shape.
  744.         
  745.         Shape ShapeBBox                             %     Compute the X center of the shape
  746.         pop exch pop 2 copy sub 2 div    %            Stack is: x1 x2 -width
  747.         neg exch pop add                            %            Stack is: x1+width
  748.         /xCenter Xdef                                    %        Store the xCenter.
  749.                 
  750.         /FirstX null def /FirstY 0 def        %        These are used by the DashStroke operator.
  751.         /LastX 0 def /LastY 0 def
  752.         
  753.         /CurrCTM matrix def                        % We need to save the CTM someplace during dashing.
  754.         /N 0 def                                            % Place holder for number of dashes on contour for autoAdvance.
  755.  
  756.         currentdict                                        % Leave a copy of the dash-dictionary on the stack.        
  757.     end
  758.     
  759. } Bdef
  760.  
  761.  
  762.  
  763. %<FF>
  764. %    This procedure draws the dash shape in the proper scale and orientation on the path.
  765. %
  766. /StampDash {
  767.  
  768.     % Grid fit the positions to avoid PS stupid round off error when contour is on pixel wide.
  769.  
  770.     LastX FirstX NotEqual
  771.     LastY FirstY NotEqual or {        % If the length of the contour is non-zero then
  772.  
  773.         CurrDash                                        % Save current dash dictionary on stack.
  774.         currentlinewidth                        % Save the current line width on the stack.
  775.         null SetDash                                % Turn off dashing while we render the dash shape to avoid recursive application of dash
  776.         CurrCTM currentmatrix                %    Save the CTM, leave copy on stack.
  777.  
  778.         FirstX FirstY translate            %    move the origin to the point to draw the dash.
  779.  
  780.         levelDash not {                            % if level-dash is disabled, rotate the CTM by the tangent of the path.
  781.  
  782.             LastY FirstY sub                        %        Do rotation based on arc-tangent of path.
  783.             LastX FirstX sub
  784.             ATanRot
  785.             
  786.         } if
  787.  
  788.         1 currentlinewidth scale        % Scale Only in Y direction by pen width
  789.         0 setlinewidth                            % Make sure framed dashes are hairlines.
  790.         0 frameOffset translate            % Do translation for inside or outside frame fill.
  791.         1 1 dashScale div scale            % Scale the pen by the line 1/scale
  792.         
  793.         breakDash {                                    % If break-dash is on, translate by the center like Skia does.
  794.             xCenter neg 0 translate
  795.         } if
  796.  
  797.         newpath 0 0 moveto
  798.         Shape begin                                    % Put shape dictionary on dict stack.
  799.             geomProc                                         %    Execute the dash geometry in transformed space
  800.             setmatrix                                        % Restore the transform so patterns in the dash aren't transformed.
  801.             fillKey QD2Fill                            % Paint the dash shape.
  802.         end
  803.         
  804.         setlinewidth                                % Restore the line width.
  805.         SetDash                                            % Restore the dash dictionary.
  806.  
  807.  
  808.     } if
  809.  
  810. } Bdef
  811.  
  812. %        The following is the set of procedures required for framing an object with a dash dictionary.
  813. %            The first 4 are the parameters to the pathforall operator.
  814. %
  815. % The lineto and curveto procedures update the last x,y point, the closepath proc does nothing.
  816. %
  817. /DashLT {/LastY Xdef /LastX Xdef} Bdef
  818. /DashCT {/LastY Xdef /LastX Xdef 4 {pop} repeat } Bdef
  819. /DashCP {} Bdef
  820.  
  821. %
  822. %        The moveto proc is the big one.  If we are at a real moveto (not one that simply moves
  823. %            to the same point as the last x,y) then we calculate the tangent and the scale
  824. %            And draw the dash shape.
  825. %
  826. /DashMT {
  827.  
  828.     FirstX null eq {                % If it was the first time for the path then
  829.     
  830.         /FirstY Xdef                    %     Save the first point on the contour.
  831.         /FirstX Xdef
  832.     
  833.     } {                                            % Else, check to see if it is a real moveto
  834.     
  835.         2 copy                                %     Copy the x,y that was passed in by pathforall
  836.         LastY ne exch                    %        Check to see if we are really at a new point or a gratuitous
  837.         LastX ne or    {                    %        one generated because PS stinks.  So if we are, draw the dash
  838.                 
  839.             StampDash                        %            Draw the dash shape in the correct orientation.
  840.                         
  841.             /FirstY Xdef                %         This moveto is now the first point of next dash.
  842.             /FirstX Xdef
  843.                     
  844.         } {                                        %        Else
  845.             pop pop                            %         we were passed a gratuitous moveto, ignore it.
  846.         } ifelse
  847.     
  848.     } ifelse
  849.     
  850. } Bdef
  851.  
  852. %<FF>
  853. %
  854. %    DashStroke:        Procedure strokes the current path, using the dash passed in.
  855. %
  856. %         frameOffset dashDict DashStroke -
  857. %
  858. %            frameOffset:    1 for inside-frame, 0 for center-frame, -1 for outside-frame
  859. %            dashDict:            A valid dashing dictionary.
  860. %
  861. /DashStroke {
  862.  
  863.     FullGsave
  864.  
  865.     begin                                    % Put the dashing dictionary on the stack.
  866.     
  867.         CurrRightIsOut {neg} if            % if rightIsOut is set, negate the frameOffset.
  868.         /frameOffset Xdef
  869.         
  870.         Shape /colorSet get SetColorSet        % Set it to be the one from the shape dict. (will be restored by fullGrestore)
  871.  
  872.         Shape /ColorSpace get dup null ne {            % Set the color space if there is one
  873.             GXSetCSpace
  874.         } {
  875.             pop
  876.         } ifelse
  877.         
  878.         % Compute advance for dashing:        
  879.         autoAdvance {
  880.         
  881.             PathLength dup advance div floor /N Xdef                        % Number of dashes that fit on contour.
  882.             N div                                                                                                % Length divided by N = new advance.
  883.         
  884.         } {            % Else just leave advance value on stack.
  885.         
  886.             advance            
  887.         
  888.         } ifelse
  889.         
  890.         /@1 Xdef            % Store temporarily in @1
  891.  
  892.  
  893.         % Compute the array for dashing. 
  894.         
  895.         Shape    ShapeBBox                                                %     Get the shape bounding box.
  896.         
  897.         BoxWidths pop                                    %        Get the width of the dash shape as first entry in dash matrix.
  898.         dup 0 eq {                                        %        But if the width is zero, we can't use it, use half advance instead
  899.             pop                                                    %            Get rid of the evil zero
  900.             @1 2 div                                        %            replace it with half the advance width, we have nothing else to go by.  Oh well.
  901.         } if
  902.         
  903.         .10 mul                                                %        Take 10% of it.  Moves tangent vector close to tangent at origin of dash shape.
  904.         dup @1 exch sub                                %        Get advance - 0.10*width as second entry in dash matrix.
  905.         [3 1 roll]                                        %        Make the dash matrix: [.1*width advance-.1*width] -  See ERS for detailed explanation.
  906.         
  907.         phase                                                 %    Get the phase of dashing.
  908.         breakDash {xCenter sub} if        % If break dash is on, then we want dash positions to be based on center
  909.                                                                     %            of dash shape rather than 0,0 , altering phase accomplishes this.
  910.                                                                     %            We do this because Skia does it in Dashing.c         
  911.                                                                                 
  912.         setdash                                                                % Set up the PostScript dash matrix parameters.
  913.         currentlinewidth                                            % Save the current line width on stack.
  914.         0 setlinewidth                                                % Make sure we get hairline contours.
  915.         /strokepath 0 AvoidLimit                            %    Get the dash contours into current path.
  916.         setlinewidth                                                    % Restore the current line width.
  917.         [] 0 setdash                                                    % Turn off PostScript dashing.
  918.         /FirstX null def                                            %    Signal the start of dashing.
  919.         
  920.         /DashMT load
  921.         /DashLT load
  922.         /DashCT load
  923.         /DashCP load 
  924.         pathforall                                                        % Stamp the dashes.
  925.         
  926.         FirstX null ne {                                                    % If there was any path to dash,
  927.             StampDash                                                                %     Force the last dash to draw, we stopped one short.
  928.         } if                                                                            % Else, if FirstX was null then there was no path.
  929.     
  930.     end
  931.     FullGrestore newpath
  932.     
  933. } Bdef
  934.  
  935.  
  936. %<FF>
  937. %            The fill procs work as follows:
  938. %                All of the procedures for the various fills are stored in a dictionary called FillDict
  939. %                The key passed to QD2Fill or QD2Clip is then used to get the procedure from the dictionary.
  940. %                The procedure is then executed.
  941. %
  942. /FillDict 7 dict dup 3 -1 roll Xdef begin        % Create a dictionary, name it FillDict.
  943.  
  944.     % Frame Fill is just stroke.
  945.     /Fr {
  946.         CurrDash null eq {                                % If no dashing then
  947.                 CurrFrame dup 0 eq {                    %     If inside frame
  948.                     stroke                                            %            just stroke
  949.                     pop
  950.                 } {                                                        %        Else                                            
  951.                     FillDict exch                                %            Get the inside or outside proc from FillDict.
  952.                     -1 eq {/Of get} {/If get} ifelse
  953.                     exec
  954.                 } ifelse
  955.                 
  956.             } {                                                            %    Else
  957.             
  958.                 CurrFrame CurrDash DashStroke    %        Execute the DashStroke procedure
  959.                 
  960.             } ifelse
  961.             
  962.         } Bdef
  963.     
  964.  
  965.     % Inside frame is done by making the current path the clip and then stroking with 2x pen.
  966.     /If
  967.         {gsave clip currentlinewidth 2 mul setlinewidth stroke grestore newpath} Bdef
  968.     
  969.  
  970.     % Outside frame is done by making the current path combined with FullPath the eoclip and
  971.     %        then stroking with 2x pen.
  972.     /Of
  973.         {gsave FullPath /eoclip 0 AvoidLimit currentlinewidth 2 mul setlinewidth stroke grestore newpath} Bdef
  974.     
  975.  
  976.     % Even-odd fill
  977.     /Eo    /eofill load def
  978.     
  979.  
  980.     % Inverse Fill is the path combined with a full path and then even-odd filled.
  981.     /In {FullPath eofill} Bdef
  982.     
  983.  
  984.     % Winding number fill is just the normal fill operator.
  985.     /W    /fill load def
  986.     
  987.     /No {newpath} Bdef                % No fill draws nothing.
  988.  
  989. end                %FillDict
  990.  
  991. %<FF>
  992. %
  993. %        Fill dictionary for patterns, needed only in level-1:
  994. %            Call the PatternFill operator properly.
  995. %
  996. languagelevel 1 eq {
  997.     /PatternFillDict 6 dict dup 3 -1 roll Xdef begin        % Create the dict, name it PatternFillDict.
  998.     
  999.         % Frame Fill:  Make the path to fill the strokepath or use dashing procedure
  1000.         /Fr {
  1001.             CurrDash null eq {                                                                % If no dashing then
  1002.                     CurrFrame dup 0 eq {                                                    %     If center frame
  1003.                         /strokepath 0 AvoidLimit true PatternFill        %            just fill stroke path with pattern.
  1004.                         pop
  1005.                     } {                                                                                        %        Else                                            
  1006.                         PatternFillDict exch                                                %            Get the inside or outside proc from FillDict.
  1007.                         -1 eq {/Of get} {/If get} ifelse
  1008.                         exec
  1009.                     } ifelse
  1010.                     
  1011.                 } {                                                            %    Else
  1012.                 
  1013.                     CurrFrame CurrDash DashStroke    %        Execute the DashStroke procedure
  1014.                     
  1015.                 } ifelse
  1016.                 
  1017.             } Bdef
  1018.         
  1019.         % Winding-number fill:
  1020.         /W {true PatternFill} Bdef
  1021.         
  1022.         %    even-odd fill
  1023.         /Eo {false PatternFill} Bdef
  1024.         
  1025.         %Inverse fill:  combine the path with a TightFullPath and do even-odd fill
  1026.         /In {TightFullPath false PatternFill} Bdef
  1027.         
  1028.         % InsideFrame:  Set up the clip to be the path, double the pen width, get the strokepath
  1029.         %        execute the PatternFill operator, restore the clip to what it was
  1030.         /If
  1031.             {gsave clip currentlinewidth 2 mul setlinewidth strokepath
  1032.                     true exch PatternFill grestore newpath} Bdef
  1033.     
  1034.         % OutsideFrame: Add the Full Path, even-odd clip, double the pen size, get the strokepath
  1035.         %            execute the PatternFill operator, restore the clip to what it was.
  1036.         /Of
  1037.             {gsave TightFullPath eoclip currentlinewidth 2 mul setlinewidth strokepath
  1038.                     true exch PatternFill grestore newpath} Bdef
  1039.     
  1040.     end
  1041.  
  1042. } if                % defined for level-1 only.
  1043.  
  1044.  
  1045. %<FF>    
  1046. %
  1047. %    QD2Fill Operator.  Does all Skia fills except dashing.  The Imaging Engine must handle this.
  1048. %
  1049. %        fillKey:        A valid Skia fill key.
  1050. %
  1051. languagelevel 1 eq {
  1052.  
  1053.     /QD2Fill {
  1054.     
  1055.         CurrPat null eq {                                % If there is no currentpatern then
  1056.             FillDict                                            %     Get the proc from FillDict
  1057.         } {                                                            %    Else
  1058.             PatternFillDict                                %  Get it from PatternFillDict
  1059.         } ifelse
  1060.         
  1061.         exch get exec                    % Execute the fill procedure according to the fillKey.
  1062.         
  1063.     } Bdef
  1064.     
  1065. } {            % LEVEL TWO!!
  1066.  
  1067.     %% Level 2 version does installs the current pattern as a color space and does
  1068.     %% a fill from the regular fill dictionary instead of the patternfill dictionary.
  1069.     
  1070.     
  1071.     % So, define procedures for installing and removing the pattern as the current color space
  1072.     
  1073.     /OldColorAndSpace [] def        % Make a dictionary entry for the old color and space.
  1074.     /OldMatrix matrix def                % Place to store the old CTM in case we muck it up for PortAllign not
  1075.     %
  1076.     %    Function: InstallPatternColorSpace
  1077.     %    Routine installs the current pattern in the persistent state as the current color space.
  1078.     %        The non-pattern color space can be restored by calling RestoreOldColorAndSpace
  1079.     %
  1080.     %        Also, as long as we're in here, deal with pattern attributes
  1081.     %
  1082.     /InstallPatternColorSpace {
  1083.             
  1084.         CurrPat null ne {                    % If the current pattern in augmented state is not null
  1085.  
  1086.             % If not PortAlligned, move user space to origin of shape to fill.
  1087.             
  1088.             CurrPat begin
  1089.             
  1090.                 PortMap PortAllign or {
  1091.     
  1092.                     OldMatrix currentmatrix pop            
  1093.                     SetupPatternCTM
  1094.                     SynchPatMatrix
  1095.                     
  1096.                 } if
  1097.                 
  1098.                 /OldColorAndSpace [
  1099.                     currentcolor currentcolorspace    %    Save the current color and color space in the array.
  1100.                 ] store
  1101.                 
  1102.                 PaintType 2 eq                                    {            % If the current pattern does not have underlying color
  1103.                     currentcolor                                                %     Get the current color components on the stack
  1104.                     dup type /dicttype eq {pop} if            %        If the current color included a pattern, get rid of it.
  1105.                 } if
  1106.  
  1107.             end
  1108.  
  1109.             CurrPat setpattern                                    % make the color and pattern the current color and pattern
  1110.  
  1111.         } if
  1112.     
  1113.     } Bdef
  1114.     
  1115.     %
  1116.     %        Function: RestoreOldColorAndSpace
  1117.     %            Routine restores the color and color space to what was stored in the OldColorAndSpace array.
  1118.     %            It only does this if there is a pattern in the persistent state, because if there isn't then
  1119.     %            InstallPatternColorSpace wouldn't have done anything.
  1120.     %
  1121.     /RestoreOldColorAndSpace {
  1122.     
  1123.         CurrPat null ne {
  1124.         
  1125.             %
  1126.             %        Fix the CTM if we changed it for attributes.
  1127.             %
  1128.             CurrPat /PortAllign get  CurrPat /PortMap get or {
  1129.             
  1130.                 OldMatrix setmatrix
  1131.                 
  1132.             } if
  1133.  
  1134.             OldColorAndSpace aload pop                        % Put the old color and space on the stack.
  1135.             setcolorspace setcolor                                % Set the grahpics state
  1136.             
  1137.         } if
  1138.         
  1139.     
  1140.     } Bdef
  1141.  
  1142.     %
  1143.     %        level 2 QD2Fill routine:
  1144.     %
  1145.     /QD2Fill {
  1146.         
  1147.         %
  1148.         %        Set the pattern in the PostScript graphics state if there is one
  1149.         %        in our persistent state.  This makes sure that our pattern is ony
  1150.         %        active during the drawing of this shape and is not actually part
  1151.         %        of the PostScript nested graphics state.
  1152.         %
  1153.         
  1154.         InstallPatternColorSpace
  1155.             
  1156.         FillDict                                % Get the fill dictionary.
  1157.         exch get exec                        % Execute the fill procedure according to the fillKey.
  1158.         
  1159.         % Set the PostScript graphics state back to normal color if we set pattern above.
  1160.         
  1161.         RestoreOldColorAndSpace
  1162.         
  1163.     } Bdef
  1164.     
  1165. } ifelse                % level 1 or level 2.
  1166.  
  1167.  
  1168.  
  1169.  
  1170. %<FF>
  1171. %
  1172. % The GlyphPaint procedure is used for painting glyphs in All cases except 
  1173. %        even-odd without pattern and inverse.
  1174. %
  1175. %        Expects the stack to be: string fillKey
  1176. %            This procedure will paint the characters one by one to avoid building a path that
  1177. %                is too big.
  1178. /GlyphPaint {
  1179.     FullGsave                                                        %        Make sure we don't screw things up.
  1180.     exch                                                                %        Get string on top of the stack.
  1181.     
  1182.     HasBold {                                                        %        If there is boldness in the current style?:
  1183.         CurrBold                                                     %            Get the boldness
  1184.         AugGstate /FontMapping get                %            We must run the boldness through the matrix
  1185.         dtransform                                                %                the font was mapped by because it was in 1pt units.
  1186.         SetBold                                                        %            Make the transformed value the current boldness
  1187.     } if
  1188.  
  1189.     {                                                                        %        And then, for each character in the string: Draw it.
  1190.                                                                             %            Stack is:  fillKey, charCode
  1191.         aChar 0 3 -1 roll put                            %            Put the character code in the string.
  1192.         dup                                                                %            Duplicate the fill key for later.
  1193.         currentpoint newpath moveto                %            Make a new path, maintain the current point.
  1194.         
  1195.         HasBold {                                                    %         If the current style contains boldness:
  1196.             
  1197.             currentpoint 3 -1 roll                    %                Save the current point, move it behind fillKey
  1198.             aChar true GXCharPath                        %                Get the path of the character.
  1199.             CurrCTM currentmatrix exch            %                Save the current transformation on the stack, behind fill key.
  1200.             CurrBold scale                                    %                scale CTM by boldness to get non-square bolding pen.
  1201.             currentlinewidth                                %                Save the current linewidth
  1202.             exch                                                        %                Move it behind the fill key.
  1203.             1 setlinewidth                                    %                set it to 1, so scaled pen = boldness
  1204.             dup /W eq                                                %                If we are doing winding number fill
  1205.             CurrPat null eq    and {                        %                And there is no pattern.
  1206.                 stroke                                                %                    Stroke the bold path.
  1207.                 3 -1 roll setmatrix                        %                    Reset the CTM
  1208.             } {                                                            %                else
  1209.                 strokepath                                        %                    Get the fillable path
  1210.                 3 -1 roll setmatrix                        %                    Reset the CTM
  1211.                 dup QD2Fill                                        %                    Paint the bold part of the glyph properly
  1212.             } ifelse
  1213.         
  1214.             exch setlinewidth                                %                restore the current line width.
  1215.             3 1 roll                                                %                Get the current point that we saved.
  1216.             moveto                                                    %                Move back there to draw the rest of the glyph.
  1217.         
  1218.         } if
  1219.         
  1220.         aChar true GXCharPath
  1221.         currentpoint                                            %            Save the point where CharPath left us.
  1222.         3 -1 roll                                                    %            Stack is now: fillKey x y fillKey
  1223.         QD2Fill
  1224.         moveto                                                        %            the Fill killed current point, move back there.
  1225.         
  1226.     } forall
  1227.     
  1228.     pop                                                                    % Pop off the last duplicate of the fill key
  1229.     currentpoint                                                %    We now want to restore the state, but keep updated 
  1230.     FullGrestore                                                %        Current point.
  1231.     moveto
  1232.     
  1233. } Bdef
  1234.     
  1235.  
  1236.  
  1237. %<FF>
  1238. %
  1239. %        Show dictionary.
  1240. %            This dictionary contains routines to do all Skia fills on text.
  1241. %
  1242. /ShowDict 7 dict dup 3 -1 roll Xdef begin        % Create a dictionary, name it ShowDict.
  1243.     
  1244.     
  1245.     % winding number is just show if no pattern and no boldness.
  1246.     
  1247.     languagelevel 1 eq {
  1248.     
  1249.         /W {CurrPat null eq HasBold not and {show} {/W GlyphPaint} ifelse} Bdef
  1250.         
  1251.     } {
  1252.     
  1253.         /W {
  1254.         
  1255.             HasBold not {
  1256.             
  1257.                 % For level-2, install the pattern color space and do a show.
  1258.                 
  1259.                 InstallPatternColorSpace show RestoreOldColorAndSpace
  1260.             
  1261.             } {
  1262.             
  1263.                 /W GlyphPaint
  1264.                 
  1265.             } ifelse
  1266.             
  1267.         } Bdef
  1268.     
  1269.     } ifelse                % level 1 or level 2
  1270.     
  1271.     
  1272.     % Inverse fill is path of whole string and a fill
  1273.     
  1274.     /In {true GXCharPath /In QD2Fill} Bdef
  1275.     
  1276.     
  1277.     %The rest simply invoke the main show procedure.
  1278.     
  1279.     /Fr {/Fr GlyphPaint} Bdef
  1280.  
  1281.     /If {/If GlyphPaint} Bdef
  1282.  
  1283.     /Of {/Of GlyphPaint} Bdef
  1284.     
  1285.     /Eo    /W load def                 %% Used to be {/Eo GlyphPaint} Bdef
  1286.     
  1287.     /No {pop} Bdef
  1288.     
  1289. end
  1290. %
  1291. %    QD2Show operator (Used in cases where the imaging engine is not in control (like when
  1292. %                                            we are drawing a character in the BuildChar of a layered font)
  1293. %                                        When the imaging engine is in control, the proper method for text
  1294. %                                        display is used (although it may end up being QD2Show sometimes)
  1295. %    
  1296. %            fillKey QD2Show -
  1297. %
  1298. %            fillKey:        A valid Skia fill key.
  1299. %
  1300. /QD2Show {
  1301.  
  1302.     ShowDict exch get exec
  1303.  
  1304. } Bdef
  1305.  
  1306.  
  1307.